package pt.inescid.components.policyengine.heimdall.core;

import java.util.Vector;

import pt.inescid.components.policyengine.heimdall.base.EventField;
import pt.inescid.components.policyengine.heimdall.base.EventObj;
import pt.inescid.components.policyengine.heimdall.base.RawEventField;
import pt.inescid.components.policyengine.heimdall.base.User;
import pt.inescid.components.policyengine.heimdall.commons.TimeUtilities;
import pt.inescid.components.policyengine.heimdall.pap.UserManagerAS;
import pt.inescid.components.policyengine.heimdall.pap.base.CompositeDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.EventFieldDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.ModelDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.PolicyDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.RuleDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.SimpleDefinition;
import pt.inescid.components.policyengine.heimdall.pdp.PolicyDecision;
import pt.inescid.components.policyengine.heimdall.pdp.base.CompositeInstance;
import pt.inescid.components.policyengine.heimdall.pdp.base.ModelInstance;
import pt.inescid.components.policyengine.heimdall.pdp.base.PolicyInstance;
import pt.inescid.components.policyengine.heimdall.pdp.base.RuleInstance;
import pt.inescid.components.policyengine.heimdall.pdp.base.SimpleInstance;

public class MainConsole {

	public static final String MODEL_TAG = "SYG";
	

	
	/* ===========================================================
	==============================================================
	==============================================================
	processEvent
	==============================================================
	==============================================================
	=========================================================== */
	public static void processEvent(EventObj ce) {

		//User currentUser = UserManagerAS.getRecord(1);
		User currentUser = new User(0,"user");
		//TODO
		ModelDefinition model = new ModelDefinition(MODEL_TAG);
		
		RuleDefinition rule = new SimpleDefinition(0,"0",null,"0");
		
		PolicyDefinition newPolicy = new PolicyDefinition("test");
		//newPolicy.addExpression(newExpression, previousLevelExp, policySection)
		model.addPolicy(newPolicy);
		currentUser.addModel(model);
		
		HeimdallServer server1 = HeimdallServer.getInstance();
		
		server1.registerProcessEventRequest(currentUser, MODEL_TAG, ce);
		synchronized (server1) {
			server1.notify();
		}
	} // testPolicyExportRemote

	
	
	/* ===========================================================
	==============================================================
	==============================================================
	wakeupServer
	==============================================================
	==============================================================
	=========================================================== */
	public static void wakeupServer() {

		HeimdallServer server1 = HeimdallServer.getInstance();
		synchronized (server1) {
			server1.notify();
		}
	} // wakeupServer

	
	
	/* ===========================================================
	==============================================================
	==============================================================
	insertEvent
	==============================================================
	==============================================================
	=========================================================== */
	public static void insertEvent(EventObj ce) {

		//User currentUser = UserManagerAS.getRecord(1);
		User currentUser = new User(0,"user");
		
		HeimdallServer server1 = HeimdallServer.getInstance();
		server1.registerStoreEventRequest(currentUser, MODEL_TAG, ce);
		synchronized (server1) {
			server1.notify();
		}
	} // testPolicyExportRemote


	/* ===========================================================
	==============================================================
	==============================================================
	insertEvent
	==============================================================
	==============================================================
	=========================================================== */
	public static void printServerQueues() {

		HeimdallServer server1 = HeimdallServer.getInstance();
		System.out.println(server1.toString());
	} // printServerQueues

	
	/* ===========================================================
	==============================================================
	==============================================================
	stopServer
	==============================================================
	==============================================================
	=========================================================== */
	public static void stopServer() {

		HeimdallServer server1 = HeimdallServer.getInstance();
		server1.setStopTag(true);
		
		synchronized (server1) {
			server1.notify();
		}
	} // stopServer

	
	
	/* ===========================================================
	==============================================================
	==============================================================
	waitASecond
	==============================================================
	==============================================================
	=========================================================== */
	public static void waitASecond(long waitTime) {

		wakeupServer();
		
		try {
			Thread.sleep(waitTime);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		wakeupServer();
	} // waitASecond

	
	
	
	/* ===========================================================
	==============================================================
	==============================================================
	main
	==============================================================
	==============================================================
	=========================================================== */
	public static void main(String[] args) {
		
		//User currentUser = UserManagerAS.getRecord(1);
		User currentUser = new User(0,"user");
		
//		Vector<RawEventField> allFields = new Vector<RawEventField>();
//		allFields.add(new RawEventField(".user.name", "sesteves"));
//		allFields.add(new RawEventField(".foo",new Integer(4)));
//		allFields.add(new RawEventField(".user.company.name", "INESC-ID"));
//		allFields.add(new RawEventField(".action.name", action));
//		allFields.add(new RawEventField(".action.value", new Integer(1)));
//		allFields.add(new RawEventField(".action.parameter[0]", "BEGIN"));
//		allFields.add(new RawEventField(".executionTime", 
//				new Long(TimeUtilities.getCurrentTime())));
		
		Vector<EventField> v = new Vector<EventField>();
		v.add(new EventField(0, "sesteves"));
		v.add(new EventField(1, 1));
		v.add(new EventField(2, 3)); 
		v.add(new EventField(3, 0));
		EventObj ce = new EventObj(0, v);
		

		ModelDefinition model = new ModelDefinition(MODEL_TAG);		
		PolicyDefinition newPolicy = new PolicyDefinition("test");
		model.addPolicy(newPolicy);		
		
		CompositeDefinition rdAND = new CompositeDefinition(RuleDefinition.LOGICAL_AND_OPERATOR, null);
		
		RuleDefinition rd1 = new EventFieldDefinition(model, RuleDefinition.EVENT_FIELD_EXPRESSION,
				"int", null, ".1");		
		RuleDefinition rd2 = new EventFieldDefinition(model, RuleDefinition.EVENT_FIELD_EXPRESSION,
				"int", null, ".2");
		RuleDefinition rd3 = new EventFieldDefinition(model, RuleDefinition.EVENT_FIELD_EXPRESSION,
				"int", null, ".3");
		
		CompositeDefinition rdOR = new CompositeDefinition(RuleDefinition.LOGICAL_OR_OPERATOR, null); 			
		CompositeDefinition rdEQS = new CompositeDefinition(RuleDefinition.EQUALS_OPERATOR, null);
		rdEQS.addOperand(rd3);
		rdEQS.addOperand(rd1);
		CompositeDefinition rdGTO = new CompositeDefinition(RuleDefinition.GREATER_THAN_OPERATOR, null);		
		rdGTO.addOperand(rd3);
		rdGTO.addOperand(rd1);
		rdOR.addOperand(rdGTO);
		rdOR.addOperand(rdEQS);
		
		CompositeDefinition rdLTO = new CompositeDefinition(RuleDefinition.LESSER_THAN_OPERATOR, null);		
		rdLTO.addOperand(rd3);
		rdLTO.addOperand(rd2);
		
		rdAND.addOperand(rdOR);
		rdAND.addOperand(rdLTO);
		
		System.out.println(rdAND.getFunction());		
		newPolicy.addExpression(rdAND, null, 0);
		newPolicy.setAuthorization(rdAND);		
		
		ModelInstance mi = new ModelInstance(ce);
		PolicyInstance pi = new PolicyInstance(newPolicy, mi);		
		CompositeInstance ci = new CompositeInstance(rdAND, mi, pi);
		
		System.out.println(ci.evaluate(mi, true));
		
		//model.addDomain(new DomainDefinition("","",true));		
		currentUser.addModel(model);
		
		HeimdallServer server1 = HeimdallServer.getInstance();
		
		server1.registerProcessEventRequest(currentUser, MainConsole.MODEL_TAG, ce);
		synchronized (server1) {
			server1.notify();
		}

		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//server1.
		
		//System.out.println(((ModelInstance)server1.eventsInLease.elementAt(0)).getDecision());
		//server1.eventsInLease.remove(0);
		//processEvent(ce);

		
/* 		
		processEvent(EventObj.getTestEvent(currentUser, "Storage"));
		insertEvent(EventObj.getTestEvent(currentUser, "Storage"));
		waitASecond(3000);

		insertEvent(EventObj.getTestEvent(currentUser, "END Storage"));
*/
		
		
		
		
		
		
		
		//
//		processEvent(EventObj.getTestEvent(currentUser, "Storage"));
//		waitASecond();
		
//		stopServer();
		
	} // main
}; // MainConsole
